# -*- coding: utf-8 -*-
"""
Task4.

Usage:
  task4.py -f <fasta_file_name>

Options:
  -h --help     Show this screen.
  -f            FASTA file name.
"""

# Coding style-guide: PEP-8
# http://legacy.python.org/dev/peps/pep-0008/

# Tool takes FASTA file with one DNA string and prints several 
# features of the string.

import sys
import os
from docopt import docopt
from Bio import SeqIO
from Bio import SeqUtils

class DNA(object):
    def __init__(self, genome):
        self._genome = genome
        
    def get_dna(self):
        print self._genome.seq
        
    def get_rna(self):
        print self._genome.seq.transcribe()
        
    def get_protein(self):
        rna = self._genome.seq.transcribe()
        print rna.translate()        
        
    def get_gc_content(self):
        print round(SeqUtils.GC(self._genome.seq), 2)
        
    def get_gc_skew(self):
        gc_skews = SeqUtils.GC_skew(self._genome.seq)
        print list(map(lambda x: round(x, 2), gc_skews))
        
    def get_weight(self):
        print round(SeqUtils.molecular_weight(self._genome.seq), 2)
 
class Invoker(object):
    def __init__(self, dna_cmd, rna_cmd, protein_cmd, get_gcc_cmd, 
                 get_gcs_cmd, get_weight_cmd):
        self.dna = dna_cmd
        self.rna = rna_cmd
        self.protein = protein_cmd
        self.gc_content = get_gcc_cmd
        self.gc_skew = get_gcs_cmd
        self.weight = get_weight_cmd

class DNAProcessor(object):
    def __init__(self, genome):
        _dna = DNA(genome)
        self._invoker = Invoker(_dna.get_dna, _dna.get_rna, _dna.get_protein, 
                                _dna.get_gc_content, _dna.get_gc_skew,
                                _dna.get_weight)
 
    def process(self, cmd):
        cmd = cmd.strip().upper()
        if cmd == "DNA":
            self._invoker.dna()
        elif cmd == "RNA":
            self._invoker.rna()
        elif cmd == "PROT":
            self._invoker.protein()
        elif cmd == "GCC":
            self._invoker.gc_content()
        elif cmd == "GCS":
            self._invoker.gc_skew()
        elif cmd == "WEIGHT":
            self._invoker.weight()
        else:
            print "Invalid command. Available commands are:" \
                   " RNA, PROT, GCC, GCS, WEIGHT."
            
def is_non_zero_file(fpath):  
    return True if os.path.isfile(fpath) and \
           os.path.getsize(fpath) > 0 else False
 
def read_genome(f):
    return SeqIO.read(f, 'fasta')


if __name__ == "__main__":
    arguments = docopt(__doc__, version='Task4 0.1')
    if not arguments['-f']:
        sys.exit('Error: FASTA file name must be presented (-f option).')
    else:
        f = arguments['<fasta_file_name>']
        if not is_non_zero_file(f):
            sys.exit('Error: file ' + f + ' is empty or does not exist.')
    
    print "Processing started..."
    print
    genome = read_genome(f)
    dna_processor = DNAProcessor(genome)
    print "Get DNA:"
    dna_processor.process("DNA")
    print
    print "Get RNA:"
    dna_processor.process("RNA")
    print
    print "Get protein:"
    dna_processor.process("PROT")
    print
    print "Calc GC content:"
    dna_processor.process("GCC")
    print
    print "Calc GC skew (100 bp window is used):"
    dna_processor.process("GCS")
    print
    print "Calc DNA weight:"
    dna_processor.process("WEIGHT")
    print
    print "Invalid command:"
    dna_processor.process("ATGC")
    print
    print "Processing finished..."
    